/** File Description
 *
 * Copyright (C) 2009 Ismail SEZEN
 * This is data file parser and part of the Windbull code.
 * -------------------------------------------------------------------------------------------
 * This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * -------------------------------------------------------------------------------------------
 * Project Name: Windbull
 * Files(4) : Windbull.c, Windbull.h, WindbullParser.c, WindbullParser.h
 * AUTHOR: Ismail SEZEN
 * e-mail: sezenismail@gmail.com
 * 13-05-2009 [12:20]
 * -------------------------------------------------------------------------------------------
 * Created by Code:Blocks 8.02
 */

/**Include Drectives*/
//{
#include <stdio.h>
#include <stdlib.h>
//}
#define HOUR 24

char **WBP_data;
int WBP_Length = 0;
int WBP_Buffer_size = 0;
char *format = "%d;%d;%d;%d;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f;%d;%f";


/**----------------------------------------------------------------------------------------------------------------------------------------
* Private
* ----------------------------------------------------------------------------------------------------------------------------------------*/
//{
/**Variables */
int _wbp_is_initialized = 0;

/**Routines */

/**
 * Function: create_2D_char_array
 * ----------------------------------
 * Creates a 2D array in the memory and returns the adress
 * @param *numrows is the number of the rows
 * @param *numcols is the number of the columns
 * returns : a pointer if the operation is succeed otherwise returns NULL (0).
*/
char** create_2D_char_array( int numrows, int numcols){
	char **data;
	data = (char **) malloc(numrows * sizeof(char *));
	if(data == NULL){
		free(data);
		printf("Memory allocation failed while allocating for dim[].\n");
		exit(-1);
	}
	//
	/* Allocate integer memory for the second dimension of a WBP_data[][]; */
	register int i;
	for(i = 0; i < numrows; i++) {
		data[i] = (char *) malloc(numcols * sizeof(char));
		if(data[i] == NULL){
			free(data[i]);
			printf("Memory allocation failed while allocating for dim[x][].\n");
			exit(-1);
		}
	}
	return *&data; // Success
}

/**
 * Function: get_file_properties
 * ----------------------------------
 * Analyses the file and returns the line count and line buffer size
 * @param *fileName is the file will be read
 * @param *length is the pointer to the line count variable
  * @param *buffer_size is the pointer to the line buffer size
 * returns : Zero (0) if  the operation is succeed otherwise returns subzero (-1).
*/
int get_file_properties(char * fileName,int *length, int *buffer_size){
	//printf("get_file_properties (%s, %d, %d)\n",fileName,*length, *buffer_size);
	FILE *f = fopen(fileName, "r");
	int line_length = 0;
	int line_count = 0;
	*buffer_size = 0;
	* length = 0;
	if(f != NULL) {
		char ch;
		while( (ch = fgetc(f)) != EOF ){
			if(ch != '\n'){
				line_length++;
				//printf("%c\n",ch);
			}else{
				line_count++; //Count the lines
				//printf("%c %d",ch, line_count);
				if(*buffer_size < line_length) {
					*buffer_size = line_length; //Get the max. line buffer size
					//printf("%d\n",*buffer_size);
				}
				line_length = 0;
			}
		}
		fclose(f);
		*length = line_count+1;
		(*buffer_size)+=3;
		//printf("File analys complated = %d, %d\n",*buffer_size, *length);
		return 0; //Success
	}
	return -1;//Failure
}

/**
 * Function: read_file_to_array
 * ----------------------------------
 * Reads the file content into a 2D array
 * @param *fileName is the file will be read
 * @param *p_arr is the pointer to the array will be written
 * @param *length is the pointer to the line count
 * @param buff_size is the length of the line on character basis
 * returns : Zero (0) if  the operation is succeed otherwise returns subzero (-1).
*/
int read_file_to_array(char *fileName, char *p_arr, int buff_size){
	FILE *f = fopen(fileName, "r");
	if(f != NULL) {
		register int i = 0;
		while(fgets((p_arr + (((i++)) * buff_size)), buff_size, f)!=NULL);
		fclose(f);
		return 0; //Success
	}
	return -1; //Failure
}

/**------------------------------------------------------*/
int parse_line_to_1D_speed_array(char *lineString,float *p_speed){
	int tmp,si;
	if( (si = sscanf(lineString, format, &tmp, &tmp,&tmp,&tmp,
				&tmp,(p_speed),
				&tmp,(p_speed+1),
				&tmp,(p_speed+2),
				&tmp,(p_speed+3),
				&tmp,(p_speed+4),
				&tmp,(p_speed+5),
				&tmp,(p_speed+6),
				&tmp,(p_speed+7),
				&tmp,(p_speed+8),
				&tmp,(p_speed+9),
				&tmp,(p_speed+10),
				&tmp,(p_speed+11),
				&tmp,(p_speed+12),
				&tmp,(p_speed+13),
				&tmp,(p_speed+14),
				&tmp,(p_speed+15),
				&tmp,(p_speed+16),
				&tmp,(p_speed+17),
				&tmp,(p_speed+18),
				&tmp,(p_speed+19),
				&tmp,(p_speed+20),
				&tmp,(p_speed+21),
				&tmp,(p_speed+22),
				&tmp,(p_speed+23)) ) == 52){
					return 0;
	}
	return -1;
}

int parse_line_to_1D_direction_array(char *lineString,int *p_direction){
	int tmp,si;
	if( (si = sscanf(lineString, format, &tmp, &tmp,&tmp,&tmp,
				(p_direction),&tmp,
				(p_direction+1),&tmp,
				(p_direction+2),&tmp,
				(p_direction+3),&tmp,
				(p_direction+4),&tmp,
				(p_direction+5),&tmp,
				(p_direction+6),&tmp,
				(p_direction+7),&tmp,
				(p_direction+8),&tmp,
				(p_direction+9),&tmp,
				(p_direction+10),&tmp,
				(p_direction+11),&tmp,
				(p_direction+12),&tmp,
				(p_direction+13),&tmp,
				(p_direction+14),&tmp,
				(p_direction+15),&tmp,
				(p_direction+16),&tmp,
				(p_direction+17),&tmp,
				(p_direction+18),&tmp,
				(p_direction+19),&tmp,
				(p_direction+20),&tmp,
				(p_direction+21),&tmp,
				(p_direction+22),&tmp,
				(p_direction+23),&tmp) ) == 52){
					return 0;
	}
	return -1;
}

int parse_line_to_1D_2array(char *lineString,float *p_speed, int *p_direction) {
	int tmp,si;
	int deg = 0;
	int *i = &deg;
	//
	if( (si = sscanf(lineString, format, &tmp, &tmp,&tmp,&tmp,
				(p_direction+(*i)),(p_speed+(*i)),
				(p_direction+(*i+1)),(p_speed+(*i+1)),
				(p_direction+(*i+2)),(p_speed+(*i+2)),
				(p_direction+(*i+3)),(p_speed+(*i+3)),
				(p_direction+(*i+4)),(p_speed+(*i+4)),
				(p_direction+(*i+5)),(p_speed+(*i+5)),
				(p_direction+(*i+6)),(p_speed+(*i+6)),
				(p_direction+(*i+7)),(p_speed+(*i+7)),
				(p_direction+(*i+8)),(p_speed+(*i+8)),
				(p_direction+(*i+9)),(p_speed+(*i+9)),
				(p_direction+(*i+10)),(p_speed+(*i+10)),
				(p_direction+(*i+11)),(p_speed+(*i+11)),
				(p_direction+(*i+12)),(p_speed+(*i+12)),
				(p_direction+(*i+13)),(p_speed+(*i+13)),
				(p_direction+(*i+14)),(p_speed+(*i+14)),
				(p_direction+(*i+15)),(p_speed+(*i+15)),
				(p_direction+(*i+16)),(p_speed+(*i+16)),
				(p_direction+(*i+17)),(p_speed+(*i+17)),
				(p_direction+(*i+18)),(p_speed+(*i+18)),
				(p_direction+(*i+19)),(p_speed+(*i+19)),
				(p_direction+(*i+20)),(p_speed+(*i+20)),
				(p_direction+(*i+21)),(p_speed+(*i+21)),
				(p_direction+(*i+22)),(p_speed+(*i+22)),
				(p_direction+(*i+23)),(p_speed+(*i+23))) ) == 52){
					//*i+=24;
					return 0;
	}
	return -1;
}
/**------------------------------------------------------*/

/**------------------------------------------------------*/
int parse_data_1D_speed_array(char *pData,int buffer_size,int line_count, float *raw_speed_array,int col_count){
	register int i;
	//printf("Line count = %d\n",line_count);
	for(i=0;i<line_count;i++){
		char *strLine = (pData + (i * buffer_size)+buffer_size);
		if(parse_line_to_1D_speed_array(strLine, (raw_speed_array + (i * col_count))) != 0){
			//printf("Parsing problem. line = %d\n",i);
			return 1;
		}
	}
	//printf("File is succesfully parsed\n\n");
	return 0;
}

int parse_data_1D_direction_array(char *pData,int buffer_size,int line_count, int *raw_direction_array,int col_count){
	register int i;
	//printf("Line count = %d\n",line_count);
	for(i=0;i<line_count;i++){
		char *strLine = (pData + (i * buffer_size)+buffer_size);
		if(parse_line_to_1D_direction_array(strLine, (raw_direction_array + (i * col_count))) != 0){
			//printf("Parsing problem. line = %d\n",i);
			return 1;
		}
	}
	//printf("File is succesfully parsed\n\n");
	return 0;
}

int parse_data_1D_2array(char *pData,int buffer_size,int line_count, float *raw_speed_array,int *raw_direction_array,int col_count){
	register int i;
	for(i=0;i<line_count;i++){
		char *strLine = (pData + (i * buffer_size));
		//printf(" Line %d %s",i,strLine);
		if(parse_line_to_1D_2array(strLine, (raw_speed_array + (i * col_count)), (raw_direction_array + (i * col_count))) != 0){
			//printf("\nParsing problem. line = %d\n",i);
			return i; // Failure
		}
	}
	//printf("File is succesfully parsed\n\n");
	return 0;// Success
}
/**------------------------------------------------------*/

/**------------------------------------------------------*/

void convert_1Darray_to_2Darray(float *p_array1D,int length,float *p_array2D, int row_count, int col_count){
	register int i,j;
	for(i=0;i<row_count;i++){
		for(j=0;j<col_count;j++){
			float *p1,*p2;
			p1 = (p_array2D + (i * col_count) + j);
			p2 = (p_array1D + (i * col_count) + j);
			p1 = p2;
		}
	}
}
//}

/**----------------------------------------------------------------------------------------------------------------------------------------
* Public Routines
* ----------------------------------------------------------------------------------------------------------------------------------------*/
//{
/**
 * Function: WBP_parse_file
 * ----------------------------------
 * Analyses and reads the file (See the header file for information)
 * @param *fileName is the file will be read
 * returns : non-Zero if  the operation is succeed otherwise returns zero (0).
*/
int WBP_read_file(char *fileName){
	//printf("WBP_read_file (%s)\n",fileName);
	/*Handle the file properties like line count and line buffer size to create a holder array*/
	if(get_file_properties(fileName,&WBP_Length,&WBP_Buffer_size) == 0) {
		//printf("WBP_length = %d WBP_Buffer_size = %d\n",WBP_Length, WBP_Buffer_size);
		/*Create 2D char array to hold the file content*/
		if((WBP_data = create_2D_char_array(WBP_Length, WBP_Buffer_size)) != NULL) {
			if(read_file_to_array(fileName, &WBP_data[0][0], WBP_Buffer_size) == 0){
				return 0; // Success
			}
		}
	}
	printf("ERROR : Error reading file!\n");
	return -1; //Failure
}

/**
 * Function: WBP_parse
 * ----------------------------------
 * Parses the file to both of speed and direction 1D arrays.
 * @param *p_speed_array is a pointer to the 1D float speed array
 * @param *p_direction_array is a pointer to the 1D integer direction array
 * returns : Zero(0) if  the operation is succeed otherwise returns negative value.
*/
int WBP_parse( float *p_speed_array,int *p_direction_array){
	return parse_data_1D_2array(&WBP_data[0][0], WBP_Buffer_size, WBP_Length, p_speed_array, p_direction_array,HOUR);
}

void WBP_Finalize(){
	if(WBP_data != NULL){
//		register int i;
//		for(i = 0; i < WBP_Length; i++){
//			if(WBP_data[i] != NULL) free(WBP_data[i]);
//		}
		free(WBP_data);
	}
}
//}
